/**
 *  @desc yêu cầu người dùng
 *  Khi người dùng thao tác trên một nút có thể chuyển trạng thái.
 *  Trạng thái nút có thể là bình thường (được mặc định), không thực hiện bất cứ hành động nào, không thể nhấp).
 *  Khi nút chuyển trạng thái, thì giao diện nút biến đổi theo trạng thái.
 *  Trong một số trường hợp người dùng không thao tác trên nút đó mà vẫn chuyển trạng thái nút đó.
 *  Danh từ:
 *  	- nút: bất kỳ nút nào
 *  	- trạng thái: tập hợp cho trước
 *  	- giao diện: tập hợp cho trước, phụ thuộc trạng thái
 *  Động từ: thao tác nút, chuyển trạng thái, thay đổi giao diện
 *  Bổ sung: không thao tác trực tiếp mà có thể thay đổi nút
 *  Mọi hành động đều độc lập nhau
 *  Mỗi trạng thái tương ứng một bản sao nút gốc
 *  Khi chuyển trạng thái, tức là hiển thị một bản ẩn những bản (sao, gốc) còn lại
 *  Cần một điểm để đánh dấu các bản sao (gốc) cùng một nhóm. Sử dụng định dạng ID-suffix
 *  @author vinhnv@live.com
 *  @since 10 giờ 39 phú tối, ngày 17 tháng 3 năm 2012
 */
var StateManager = {
        /**
	 * @desc đảm bảo tạo mới
	 * @author vinhnv@live.com
	 * @since 18/03/2012
	 */
        always_create: true,
	/**
	 * @desc lưu trữ tất cả sự kiện một nút có thể có
	 * @author vinhnv@live.com
	 * @since 18/03/2012
	 */
	all_events: {
		'click': 'onclick',
		'change': 'onchange'
	},
        /**
	 * @desc lưu trữ những trạng thái của nút
	 * @author vinhnv@vnext.vn
	 */
	states: {
		// Trạng thái dành cho bản gốc
		undefined: {
			suffix: '',  // bản gốc không có hậu tố
			'class': '', // bản gốc không thêm lớp mới
			event: undefined // or null giữ nguyên hành động
		},
		// Mọi hành động đều được chấp nhận
		all_enable: {
			suffix: '-all_enable',
			'class': 'all_enable',
			event: undefined // or null giữ nguyên hành động
		},
		// Mọi hành động đều không được chấp nhận
		all_disable: {
			suffix: '-all_disable',
			'class': 'off', // Chỉ sử dụng class off để tránh trường hợp button dù đã disable nhưng vẫn hover
			event: '' // disable all
		},
		// Chỉ hành động nhấp chuột không được chấp nhận
		not_clickable: {
			suffix: '-not_clickable',
			'class': 'not_clickable',
			event: 'click' // split by ','
		}
	},
	/**
	 * @desc khởi tạo
	 * @author vinhnv@live.com
	 * @since 18/03/2012
	 */
	init: function() {
		
	},
	/**
	 * @desc chuyển trạng thái
	 * @author vinhnv@live.com
	 * @since 18/03/2012
	 */
	switchTo: function(id, to_state) {
		var i, j; // duyệt đối tượng, mảng
		var list_event = []; // liệt kê danh sách sự kiện bị loại bỏ
		var stop = false; // cờ để xác nhận có dừng thực thi
		var create = false; // cờ để xác định có tạo bản sao hay không
		var newId; // lưu trữ id của bản sao mới
		
		// Kiểm tra tồn tại nút này (bản gốc) không
		$('#' + id).length > 0 ? null : stop = true;
		if(stop) {
			alert('Không tồn tại biến này');
			return;
		} else {}
		
		// Kiểm tra tồn tại trạng thái này không
		this.states[to_state] != undefined ? null : stop = true;
		if(stop) {
			alert('Không tồn tại trạng thái này');
			return;
		} else {}
		
		// Xác nhận id của bản sao
		newId = id + this.states[to_state]['suffix'];
		
                if(newId != id && this.always_create == true) {
                    $('#' + newId).remove();
                } else {}
                
		// Kiểm tra bản sao cho trạng thái này đã tồn tại chưa
		$('#' + newId).length > 0 ? null : create = true;
		
		// Nếu chưa thì tạo bản sao, và nối ngay vào sau nút gốc
		if(create) {
			// Tạo mới bản sao từ bản gốc với id mới
			newButton = $('#' + id).clone().attr('id', newId);
			
			// Lấy ra bản sao thực sự chứ không phải mảng
			newButton = newButton[0];
			
			// Lấy danh sách event để loại bỏ
			list_event = this.states[to_state]['event'];
			
			// Nếu danh sách event đã được chỉ ra thì loại bỏ theo đó
			// Ngược lại không loại bỏ bất cứ hành động nào
			if(list_event != undefined) {
				list_event = list_event.split(',');
				// Nếu danh sách event là rỗng, thì loại bỏ tất cả hành động
				if(list_event.length == 1 && list_event[0] == '') {
					$(newButton).unbind(); // đập hết hành động
					$(newButton).die(); // đập hết hành động
					// duyệt tất cả hành động và loại bỏ
					for(j in this.all_events) {
						eval("$(newButton)[0]." + this.all_events[j] + " = null;"); // dùng thuộc tính js thuần
						eval("$(newButton).attr('" + this.all_events[j] + "', null);"); // dùng hàm jquery thay đổi thuộc tính
					}
				} else {
					// Loại bỏ những hành động có trong danh sách
					for(i in list_event) {
						if(list_event[i] != '') {
							$(newButton).unbind(list_event[i]); // đập hết hành động
							$(newButton).die(list_event[i]); // đập hết hành động
							eval("$(newButton)[0].on" + list_event[i] + " = null;"); // dùng thuộc tính js thuần
							eval("$(newButton).attr('on" + list_event[i] + "', null);"); // dùng hàm jquery thay đổi thuộc tính
						} else {}
					}
				}
			} else {}
			
			// Đính chính lại giao diện (thêm loại bỏ lớp)
			// Loại bỏ cho nút mới lớp của những bản sao
			for(i in this.states) {
				$(newButton).removeClass(this.states[i]['class']);
			}
			
			// Thêm class của bản sao hiện tại
			$(newButton).addClass(this.states[to_state]['class']);
			
			// Thêm vào sau nút gốc
			$(newButton).insertAfter($('#' + id));
		} else {}
		
		// Ẩn mọi bản sao
		$('[id^=' + id + ']').hide();
                
		// Hiển thị bản sao tương ứng với trạng thái
		$('#' + newId).show();
	}
}

// Khởi tạo quản lý trạng thái nút
StateManager.init();
// Thêm plugin cho jquery
(function($){
// Hàm chuyển trạng thái
 $.fn.switchStateTo = function(state) {
    // Xác nhận trạng thái là kiểu chuỗi hoặc undefined
    typeof state != 'string' && typeof state != 'undefined' ? state = '': null;
    // Nếu trạng thái là chuỗi rỗng thì không xử lý gì
    if(state == '') {
        return;
    } else {}
    
    return this.each(function() {
        // Thực hiện chuyển trạng thái
        StateManager.switchTo(this.id, state);
    });
 };
})(jQuery);